package net.borderwars.userserver;

import net.borderwars.beans.Player;
import net.borderwars.beans.Robot;
import net.borderwars.util.DBSession;
import net.borderwars.util.HibernateUtil;
import org.hibernate.criterion.Expression;

import java.io.*;
import java.sql.SQLException;
import java.util.*;

/**
 * @author ehubbard
 *         Date: May 5, 2006
 *         Time: 11:05:19 AM
 */
public class ClientConnection implements ServerInterface {
    private String username;
    private String pass;
    private HashMap<Integer, Object> objects = new HashMap<Integer, Object>();

    public static ClientConnection login(String username, String pass) throws SQLException {
        ClientConnection cc = new ClientConnection(username, pass);
        cc.setLastLogin();
        return (cc);
    }

    private ClientConnection(String username, String pass) {
        this.username = username;
        this.pass = pass;
    }

    public String getUsername() {
        return username;
    }

    public Object getServerSideObject(Integer key) {
        return (objects.get(key));
    }

    public List<Robot> getPublicRobots() throws SQLException {
        DBSession s = HibernateUtil.getSession();
        List l = s.createCriteria(Robot.class).add(Expression.eq("publicDomain", new Boolean(true))).list();
        List<Robot> rtn = new ArrayList<Robot>();
        rtn.addAll(l);
        s.close();
        return (rtn);
    }

    public String compile(Robot r) throws IOException, InterruptedException, SQLException {

        File f = new File(r.getName() + ".java");
        String name = f.getCanonicalPath();
        FileWriter fw = new FileWriter(f);
        fw.write(r.getSource());
        fw.close();

        String compiler = Server.getCompiler();
        String cmd = compiler + " -g -cp sdk.jar " + name;
        Server.log.info("about to execute:\n" + cmd);
        Process p = Runtime.getRuntime().exec(cmd);
        BufferedReader br = new BufferedReader(new InputStreamReader(p.getErrorStream()));
        OutputGrabber og = new OutputGrabber(br);
        int exit = p.waitFor();
        if (exit == 0) { // if it compiled fine.. go ahead and save out the robot with the new bytecode
            File ff = new File(r.getName() + ".class");
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(ff));
            byte data[] = new byte[(int) ff.length()];
            bis.read(data);
            bis.close();
            r.setByteCode(data);
            saveRobot(r);
        }
        System.out.println("Exit Code of " + exit);
        return (og.total);
    }

    public byte[] getBytes(Robot r) throws IOException, InterruptedException, SQLException {
        String results = compile(r);
        if (results.length() < 5) { // if it compiled okay
            File f = new File(r.getName() + ".class");
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(f));
            byte data[] = new byte[(int) f.length()];
            bis.read(data);
            bis.close();
            return (data);
        } else {
            return (null);
        }
    }

    static public class OutputGrabber extends Thread {
        BufferedReader br;
        String total = "";

        public OutputGrabber(BufferedReader br) {
            this.br = br;
            start();
        }

        public void run() {
            String line = null;
            try {
                line = br.readLine();
                while (line != null) {
                    System.out.println("GRAB: " + line);
                    total += line + "\n"; // gotta put the /n back on.. they get stripped from the readLine()
                    line = br.readLine();
                }
            }
            catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public Robot saveRobot(Robot r) throws SQLException {
        DBSession s = HibernateUtil.getSession();
        r.setByteCode(null);
        r = (Robot) s.merge(r);
        s.flush();
        s.close();
        return (r);
    }

    public Player getPlayer() throws SQLException {
        DBSession s = HibernateUtil.getSession();
        List l = s.createCriteria(Player.class).add(Expression.eq("name", username)).list();
        Player rtn = (Player) l.get(0);
        s.close();
        return (rtn);
    }

    public Map getObjects() {
        return (objects);
    }

    private void setLastLogin() throws SQLException {
        DBSession s = HibernateUtil.getSession();
        List l = s.createCriteria(Player.class).add(Expression.eq("name", username)).list();
        if (l.size() == 0) {
            System.out.println("Could not find " + username + " in the database!");
        }
        Player rtn = (Player) l.get(0);
        rtn.setLastLogin(new Date());
        s.save(rtn);
        s.close();
    }

}
